package com.filetransfer.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.filetransfer.dao.DeviceMapper;
import com.filetransfer.dao.MessageMapper;
import com.filetransfer.model.dto.MessageDTO;
import com.filetransfer.model.entity.Device;
import com.filetransfer.model.entity.Message;
import com.filetransfer.service.MessageService;
import com.filetransfer.websocket.WebSocketServer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 消息服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MessageServiceImpl implements MessageService {

    private final MessageMapper messageMapper;
    private final DeviceMapper deviceMapper;
    private final WebSocketServer webSocketServer;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long sendMessage(MessageDTO messageDTO) {
        Message message = new Message();
        BeanUtils.copyProperties(messageDTO, message);
        
        // 设置默认状态和时间
        message.setStatus(0); // 未读
        message.setCreateTime(LocalDateTime.now());
        
        messageMapper.insert(message);
        
        // 通过WebSocket通知接收者
        try {
            webSocketServer.sendMessageToDevice(message.getReceiverId(), convertToDTO(message, message.getReceiverId()));
        } catch (Exception e) {
            log.error("WebSocket发送消息失败: {}", e.getMessage());
        }
        
        return message.getId();
    }
    
    @Override
    public boolean updateStatus(Long id, Integer status) {
        LambdaUpdateWrapper<Message> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Message::getId, id)
                .set(Message::getStatus, status);
        
        return messageMapper.update(null, updateWrapper) > 0;
    }
    
    @Override
    public List<MessageDTO> getMessagesBetween(String deviceId1, String deviceId2) {
        LambdaQueryWrapper<Message> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper
                .and(w -> w
                        .eq(Message::getSenderId, deviceId1)
                        .eq(Message::getReceiverId, deviceId2))
                .or(w -> w
                        .eq(Message::getSenderId, deviceId2)
                        .eq(Message::getReceiverId, deviceId1)))
                .ne(Message::getStatus, 2) // 排除已删除消息
                .orderByAsc(Message::getCreateTime);
        
        return messageMapper.selectList(queryWrapper)
                .stream()
                .map(message -> convertToDTO(message, deviceId1))
                .collect(Collectors.toList());
    }
    
    @Override
    public int getUnreadCount(String receiverId) {
        LambdaQueryWrapper<Message> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Message::getReceiverId, receiverId)
                .eq(Message::getStatus, 0); // 未读
        
        return messageMapper.selectCount(queryWrapper).intValue();
    }
    
    @Override
    public boolean markAsRead(Long messageId) {
        LambdaUpdateWrapper<Message> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Message::getId, messageId)
                .set(Message::getStatus, 1); // 已读
        
        return messageMapper.update(null, updateWrapper) > 0;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int markAllAsRead(String senderId, String receiverId) {
        LambdaUpdateWrapper<Message> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Message::getSenderId, senderId)
                .eq(Message::getReceiverId, receiverId)
                .eq(Message::getStatus, 0) // 未读
                .set(Message::getStatus, 1); // 已读
        
        return messageMapper.update(null, updateWrapper);
    }
    
    @Override
    public MessageDTO convertToDTO(Message message, String currentDeviceId) {
        if (message == null) {
            return null;
        }
        
        MessageDTO messageDTO = new MessageDTO();
        BeanUtils.copyProperties(message, messageDTO);
        
        // 获取发送者和接收者名称
        Device sender = deviceMapper.selectById(message.getSenderId());
        Device receiver = deviceMapper.selectById(message.getReceiverId());
        
        if (sender != null) {
            messageDTO.setSenderName(sender.getDeviceName());
        }
        
        if (receiver != null) {
            messageDTO.setReceiverName(receiver.getDeviceName());
        }
        
        // 设置是否是自己发送的消息
        messageDTO.setSelf(Objects.equals(message.getSenderId(), currentDeviceId));
        
        // 设置消息类型描述
        messageDTO.setTypeDesc(getTypeDesc(message.getType()));
        
        // 设置消息状态描述
        messageDTO.setStatusDesc(getStatusDesc(message.getStatus()));
        
        return messageDTO;
    }
    
    /**
     * 获取消息类型描述
     * @param type 类型
     * @return 类型描述
     */
    private String getTypeDesc(Integer type) {
        if (type == null) {
            return "未知";
        }
        
        switch (type) {
            case 0: return "文本";
            case 1: return "图片";
            case 2: return "文件";
            case 3: return "系统消息";
            default: return "未知";
        }
    }
    
    /**
     * 获取消息状态描述
     * @param status 状态
     * @return 状态描述
     */
    private String getStatusDesc(Integer status) {
        if (status == null) {
            return "未知";
        }
        
        switch (status) {
            case 0: return "未读";
            case 1: return "已读";
            case 2: return "已删除";
            default: return "未知";
        }
    }
} 